﻿/*++

Copyright (c) 2011 Rainr Corporation

Module Name:

	Rainr.Utilities.Security.EncryptUtility

Abstract:

	加解密工具类

Author:

	Zhou Junyu (Rainr)    2011-01-01

Revision History:
  
--*/

using System.Text;
using System;
using System.Security.Cryptography;
using System.IO;

namespace Rainr.Utilities.Security
{
    /// <summary>
    /// 加解密工具类
    /// </summary>
    public static class CryptographyUtility
    {
        #region 对称加密
        /// <summary>
        /// DES加密
        /// </summary>
        /// <param name="encryptKey">密钥(8字符)</param>
        /// <param name="encryptString">平文</param>
        /// <returns>成功：加密后的密文；失败：NULL</returns>
        public static string DES_Encrypt(string encryptKey, string encryptString)
        {
            string result = null;
            using (DESCryptoServiceProvider desCryptoService = new DESCryptoServiceProvider())
            {
                desCryptoService.IV = DES_IV;
                desCryptoService.Key = RepairByteKey(encryptKey, 8);
                byte[] encryptStringBytes = Encoding.UTF8.GetBytes(encryptString);
                MemoryStream ms = null;
                try
                {
                    ms = new MemoryStream();
                    using (CryptoStream cs = new CryptoStream(ms, desCryptoService.CreateEncryptor(), CryptoStreamMode.Write))
                    {
                        cs.Write(encryptStringBytes, 0, encryptStringBytes.Length);
                        cs.FlushFinalBlock();
                        cs.Close();
                    }
                    result = Convert.ToBase64String(ms.ToArray());
                }
                catch (Exception)
                {
                    result = null;
                }
                finally
                {
                    if (ms != null) ms.Close();
                }
            }
            return result;
        }
        /// <summary>
        /// DES解密
        /// </summary>
        /// <param name="decryptKey">密钥(8字符)</param>
        /// <param name="decryptString">密文</param>
        /// <returns>成功：解密后的平文；失败：NULL</returns>
        public static string DES_Decrypt(string decryptKey, string decryptString)
        {
            string result = null;
            using (DESCryptoServiceProvider desCryptoService = new DESCryptoServiceProvider())
            {
                desCryptoService.IV = DES_IV;
                desCryptoService.Key = RepairByteKey(decryptKey, 8);
                MemoryStream ms = null;
                try
                {
                    byte[] encryptStringBytes = Convert.FromBase64String(decryptString);
                    ms = new MemoryStream();
                    using (CryptoStream cs = new CryptoStream(ms, desCryptoService.CreateDecryptor(), CryptoStreamMode.Write))
                    {
                        cs.Write(encryptStringBytes, 0, encryptStringBytes.Length);
                        cs.FlushFinalBlock();
                        cs.Close();
                    }
                    result = Encoding.UTF8.GetString(ms.ToArray());
                }
                catch (Exception)
                {
                    result = null;
                }
                finally
                {
                    if (ms != null) ms.Close();
                }
            }
            return result;
        }
        /// <summary>
        /// AES加密
        /// </summary>
        /// <param name="encryptKey">密钥(32字符)</param>
        /// <param name="encryptString">平文</param>
        /// <returns>成功：加密后的密文；失败：NULL</returns>
        public static string AES_Encrypt(string encryptKey, string encryptString)
        {
            string result = null;
            using (Rijndael aesCryptoService = Rijndael.Create())
            {
                aesCryptoService.IV = AES_IV;
                aesCryptoService.Key = RepairByteKey(encryptKey, 32);
                byte[] encryptStringBytes = Encoding.UTF8.GetBytes(encryptString);
                MemoryStream ms = null;
                try
                {
                    ms = new MemoryStream();
                    using (CryptoStream cs = new CryptoStream(ms, aesCryptoService.CreateEncryptor(), CryptoStreamMode.Write))
                    {
                        cs.Write(encryptStringBytes, 0, encryptStringBytes.Length);
                        cs.FlushFinalBlock();
                        cs.Close();
                    }
                    result = Convert.ToBase64String(ms.ToArray());
                }
                catch (Exception)
                {
                    result = null;
                }
                finally
                {
                    if (ms != null) ms.Close();
                }
            }
            return result;
        }
        /// <summary>
        /// AES解密
        /// </summary>
        /// <param name="decryptKey">密钥(32字符)</param>
        /// <param name="decryptString">密文</param>
        /// <returns>成功：解密后的平文；失败：NULL</returns>
        public static string AES_Decrypt(string decryptKey, string decryptString)
        {
            string result = null;
            using (Rijndael aesCryptoService = Rijndael.Create())
            {
                aesCryptoService.IV = AES_IV;
                aesCryptoService.Key = RepairByteKey(decryptKey, 32);
                MemoryStream ms = null;
                try
                {
                    byte[] encryptStringBytes = Convert.FromBase64String(decryptString);
                    ms = new MemoryStream();
                    using (CryptoStream cs = new CryptoStream(ms, aesCryptoService.CreateDecryptor(), CryptoStreamMode.Write))
                    {
                        cs.Write(encryptStringBytes, 0, encryptStringBytes.Length);
                        cs.FlushFinalBlock();
                        cs.Close();
                    }
                    result = Encoding.UTF8.GetString(ms.ToArray());
                }
                catch (Exception)
                {
                    result = null;
                }
                finally
                {
                    if (ms != null) ms.Close();
                }
            }
            return result;
        }
        #endregion

        #region 非对称加密
        /// <summary>
        /// 产生一对RSA的公钥私钥
        /// </summary>
        /// <param name="privateKey">产生的私钥</param>
        /// <param name="publicKey">产生的公钥</param>
        public static void RSA_CreateKeys(out string privateKey, out string publicKey)
        {
            try
            {
                RSACryptoServiceProvider rsaCryptoService = new RSACryptoServiceProvider();
                privateKey = rsaCryptoService.ToXmlString(true);
                publicKey = rsaCryptoService.ToXmlString(false);
            }
            catch (Exception)
            {
                privateKey = null;
                publicKey = null;
            }
        }
        /// <summary>
        /// 使用公钥对明文进行RSA加密
        /// </summary>
        /// <param name="publicKey">公钥</param>
        /// <param name="encryptString">平文</param>
        /// <returns>加密后的密文</returns>
        public static string RSA_Encrypt(string publicKey, string encryptString)
        {
            string result = null;
            RSACryptoServiceProvider rsaCryptoService = null;
            try
            {
                byte[] encryptStringBytes = Encoding.UTF8.GetBytes(encryptString);
                rsaCryptoService = new RSACryptoServiceProvider();
                rsaCryptoService.FromXmlString(publicKey);
                result = Convert.ToBase64String(rsaCryptoService.Encrypt(encryptStringBytes, false));
            }
            catch (Exception)
            {
                result = null;
            }
            finally
            {
                if (rsaCryptoService != null) rsaCryptoService.Clear();
            }
            return result;
        }
        /// <summary>
        /// 使用私钥对明文进行RSA解密
        /// </summary>
        /// <param name="privateKey">私钥</param>
        /// <param name="encryptString">密文</param>
        /// <returns>解密后的平文</returns>
        public static string RSA_Decrypt(string privateKey, string decryptString)
        {
            string result = null;
            RSACryptoServiceProvider rsaCryptoService = null;
            try
            {
                byte[] decryptStringBytes = Convert.FromBase64String(decryptString);
                rsaCryptoService = new RSACryptoServiceProvider();
                rsaCryptoService.FromXmlString(privateKey);
                result = Encoding.UTF8.GetString(rsaCryptoService.Decrypt(decryptStringBytes, false));
            }
            catch (Exception)
            {
                result = null;
            }
            finally
            {
                if (rsaCryptoService != null) rsaCryptoService.Clear();
            }
            return result;
        }
        #endregion

        #region 散列加密
        /// <summary>
        /// MD5加密(结果为32字符)
        /// 这个加密过程是不可逆的
        /// </summary>
        /// <param name="encryptString">平文</param>
        /// <returns>成功：返回加密后密文(32字符)；失败：NULL</returns>
        public static string MD5_Encode(string encryptString)
        {
            string result = null;
            using (MD5CryptoServiceProvider md5CryptoService = new MD5CryptoServiceProvider())
            {
                try
                {
                    result = BitConverter.ToString(md5CryptoService.ComputeHash(Encoding.UTF8.GetBytes(encryptString))).Replace("-", "");
                }
                catch (Exception)
                {
                    result = null;
                }
            }
            return result;
        }
        /// <summary>
        /// MD5加密返回Base64字符串(结果为24字符)
        ///  这个加密过程是不可逆的
        /// </summary>
        /// <param name="encryptString">平文</param>
        /// <returns>加密后的密文(24字符)；失败：NULL</returns>
        public static string MD5_EncodeToBase64(string encryptString)
        {
            string result = null;
            using (MD5CryptoServiceProvider md5CryptoService = new MD5CryptoServiceProvider())
            {
                try
                {
                    result = Convert.ToBase64String(md5CryptoService.ComputeHash(Encoding.UTF8.GetBytes(encryptString)));
                }
                catch (Exception)
                {
                    result = null;
                }
            }
            return result;
        }
        /// <summary>
        /// SHA1加密(结果为40字符)
        /// 这个加密过程是不可逆的
        /// </summary>
        /// <param name="encryptString">平文</param>
        /// <returns>成功：返回加密后密文(40字符)；失败：NULL</returns>
        public static string SHA1_Encode(string encryptString)
        {
            string result = null;
            using (SHA1CryptoServiceProvider sha1CryptoService = new SHA1CryptoServiceProvider())
            {
                try
                {
                    result = BitConverter.ToString(sha1CryptoService.ComputeHash(Encoding.UTF8.GetBytes(encryptString))).Replace("-", "");
                }
                catch (Exception)
                {
                    result = null;
                }
            }
            return result;
        }
        /// <summary>
        /// SHA1加密返回Base64字符串(结果为28字符)
        /// 这个加密过程是不可逆的
        /// </summary>
        /// <param name="encryptString">平文</param>
        /// <returns>加密后的密文(28字符)；失败：NULL</returns>
        public static string SHA1_EncodeToBase64(string encryptString)
        {
            string result = null;
            using (SHA1CryptoServiceProvider sha1CryptoService = new SHA1CryptoServiceProvider())
            {
                try
                {
                    result = Convert.ToBase64String(sha1CryptoService.ComputeHash(Encoding.UTF8.GetBytes(encryptString)));
                }
                catch (Exception)
                {
                    result = null;
                }
            }
            return result;
        }
        /// <summary>
        /// SHA512加密(结果128字符)
        /// 这个加密过程是不可逆的
        /// 这个加密至今还是安全的没有找到碰撞点.
        /// </summary>
        /// <param name="encryptString"></param>
        /// <returns></returns>
        public static string SHA512_Encode(string encryptString)
        {
            string result = null;
            SHA512 sha512 = null;
            try
            {
                sha512 = SHA512Managed.Create();
                result = BitConverter.ToString(sha512.ComputeHash(Encoding.UTF8.GetBytes(encryptString))).Replace("-", "");
            }
            catch (Exception)
            {
                result = null;
            }
            finally
            {
                if (sha512 != null) sha512.Clear();
            }
            return result;
        }
        /// <summary>
        /// SHA512加密返回Base64字符串(结果88字符)
        /// 这个加密过程是不可逆的
        /// 这个加密至今还是安全的没有找到碰撞点.
        /// </summary>
        /// <param name="encryptString"></param>
        /// <returns></returns>
        public static string SHA512_EncodeToBase64(string encryptString)
        {
            string result = null;
            SHA512 sha512 = null;
            try
            {
                sha512 = SHA512Managed.Create();
                result = Convert.ToBase64String(sha512.ComputeHash(Encoding.UTF8.GetBytes(encryptString))).Replace("-", "");
            }
            catch (Exception)
            {
                result = null;
            }
            finally
            {
                if (sha512 != null) sha512.Clear();
            }
            return result;
        }
        #endregion

        #region 合并加密
        /// <summary>
        /// 联合加密(结果为40字符)。
        /// 使用MD5,AES,SHA1等一起加密数据,使数据相对安全些。
        /// 这个加密过程是不可逆的。
        /// </summary>
        /// <param name="encryptString">平文</param>
        /// <returns>密文(40字符)</returns>
        public static string UnionEncode(string encryptString)
        {
            string resultmd5 = MD5_Encode(encryptString);
            return SHA1_Encode(AES_Encrypt(resultmd5, resultmd5));
        }
        #endregion

        #region 公共向量
        /// <summary>
        /// DES加解密向量
        /// </summary>
        private static byte[] DES_IV = new byte[] { 0X72, 0X61, 0X69, 0X6E, 0X72, 0X64, 0X65, 0X73 };
        /// <summary>
        /// AES加解密向量
        /// </summary>
        private static byte[] AES_IV = new byte[] { 0X72, 0X61, 0X69, 0X6E, 0X72, 0X61, 0X65, 0X73, 0X72, 0X61, 0X69, 0X6E, 0X72, 0X61, 0X65, 0X73 };
        #endregion

        #region 公共方法
        /// <summary>
        /// 修改修补KEY到特定长度
        /// </summary>
        /// <param name="sourceKey">原Key</param>
        /// <param name="targetKeyLenght">目标Key长度</param>
        /// <returns>修改后的Key</returns>
        private static byte[] RepairByteKey(string sourceKey, int targetKeyLenght)
        {
            if (string.IsNullOrEmpty(sourceKey)) sourceKey = "RAINRKEY";
            if (sourceKey.Length < targetKeyLenght) sourceKey = sourceKey.PadRight(targetKeyLenght, 'X');
            byte[] byteKey = Encoding.UTF8.GetBytes(sourceKey);
            byte[] resultByteKey = new byte[targetKeyLenght];
            Array.Copy(byteKey, 0, resultByteKey, 0, targetKeyLenght);
            return resultByteKey;
        }
        #endregion
    }
}
